use crate::core::traits::Dot;
use crate::vector::items::Items;
use crate::vector::matrix::Matrix;
use crate::vector::traits::ItemOps;
use std::cmp::min;
use std::fmt::{Debug, Formatter};
use std::ops::{Add, Div, Index, IndexMut, Mul, Sub};

/**
矩阵
 **/
pub struct Vector<T: Clone> {
    pub(crate) data: Items<T>,
    current: usize,
}

impl<T: Clone> Vector<T> {
    pub const fn new(args: Vec<T>) -> Self {
        Self {
            data: Items(args),
            current: 0,
        }
    }

    pub const fn new_from_items(args: Items<T>) -> Self {
        Self {
            data: args,
            current: 0,
        }
    }
    //设置每一维的元素
    pub fn set_data(&mut self, args: Vec<T>) {
        for r in 0..min(self.len(), args.len()) {
            self[r] = args[r].clone();
        }
    }
}

impl<T> Vector<T>
where
    T: ItemOps,
    Items<T>: Dot<T>,
{
    pub fn dot(&self, other: Self) -> T {
        assert_eq!(self.len(), other.len());
        self.data.dot(other.data)
    }

    pub fn extend(&self, new_size: usize) -> Self {
        let mut vector = Self::new(vec![T::default(); new_size]);
        vector.set_data(self.data.clone().0);
        vector
    }

    pub fn cross(&self, other: Self) -> Self {
        assert_eq!(self.len(), other.len());
        assert!(self.len() == 3 || self.len() == 2);

        let vector1 = self.extend(3);
        let vector2 = other.extend(3);

        let mut matrix = Matrix::new(
            (vector1.len() as i32).try_into().unwrap(),
            (vector1.len() as i32).try_into().unwrap(),
        );
        let matrix_data = vec![
            T::default(),
            T::default() - vector1[2].clone(),
            vector1[1].clone(),
            vector1[2].clone(),
            T::default(),
            T::default() - vector1[0].clone(),
            T::default() - vector1[1].clone(),
            vector1[0].clone(),
            T::default(),
        ];

        matrix.set_data(matrix_data);

        matrix * vector2
    }

    fn norm(&self) -> T {
        self.data.iter().map(|x| x.clone() * x.clone()).sum()
    }

    pub(crate) fn get_identity(self) -> Self {
        let modulus = self.norm();
        assert_ne!(modulus, T::default());

        self / modulus
    }
}

impl<T: Clone> Index<usize> for Vector<T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        &self.data[index]
    }
}

impl<T: Clone> IndexMut<usize> for Vector<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.data[index]
    }
}

impl<T: Clone> Iterator for Vector<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.data.len() {
            None
        } else {
            let item = self.data[self.current].clone();
            self.current += 1;
            Some(item)
        }
    }
}

impl<T: Clone> ExactSizeIterator for Vector<T> {
    fn len(&self) -> usize {
        self.data.len()
    }
}

impl<T: Clone> Clone for Vector<T> {
    fn clone(&self) -> Self {
        Self {
            data: self.data.clone(),
            current: 0,
        }
    }
}

impl<T: Clone + Add> Add for Vector<T>
where
    Vec<T>: FromIterator<<T as Add>::Output>,
{
    type Output = Vector<T>;

    fn add(self, rhs: Self) -> Self {
        assert_eq!(self.len(), rhs.len());

        let data = self.data + rhs.data;

        Self::new_from_items(data)
    }
}

impl<T: Clone + Sub> Sub for Vector<T>
where
    Vec<T>: FromIterator<<T as Sub>::Output>,
{
    type Output = Vector<T>;

    fn sub(self, rhs: Self) -> Self {
        assert_eq!(self.len(), rhs.len());

        let data = self.data - rhs.data;

        Self::new_from_items(data)
    }
}

impl<T: Clone + Mul<T>> Mul<T> for Vector<T>
where
    Vec<T>: FromIterator<<T as Mul<T>>::Output>,
    Items<T>: Mul<T, Output = Items<T>>,
{
    type Output = Vector<T>;

    fn mul(self, rhs: T) -> Self::Output {
        let data = self.data * rhs;

        Self::new_from_items(data)
    }
}

impl<T: Clone + Mul<f64, Output = T>> Mul<Vector<T>> for f64
where
    Vec<T>: FromIterator<<T as Mul<f64>>::Output>,
{
    type Output = Vector<T>;

    fn mul(self, rhs: Vector<T>) -> Vector<T> {
        let data = self * (rhs.data);

        Vector::new_from_items(data)
    }
}

impl<T: Clone + Div> Div<T> for Vector<T>
where
    Vec<T>: FromIterator<<T as Div<T>>::Output>,
{
    type Output = Vector<T>;

    fn div(self, rhs: T) -> Self::Output {
        let data = self.data / rhs;

        Self::new_from_items(data)
    }
}

impl<T: Debug + Clone> Debug for Vector<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("Vector").field(&self.data).finish()
    }
}
